import * as THREE from 'three';
import type { LightType } from "@/types/components/three.d.ts"

interface LightOptions {
    intensity?: number;
    color?: THREE.ColorRepresentation; // 使用 Three.js 的颜色类型
    distance?: number; // 点光源/聚光灯专用
    angle?: number;    // 聚光灯专用
    decay?: number;    // 点光源/聚光灯专用
    castShadow?: boolean; // 定向光/聚光灯专用
    position?: THREE.Vector3Tuple; // [x, y, z]
}


export default class Light {

    public readonly type: LightType;
    public intensity: number;  // 默认不透明
    public color: THREE.Color;  // 默认白色
    public instance: THREE.Light; // 实际的光源实例

    // Required<LightOptions> 确保所有选项在合并后都不会是 undefined
    private static DEFAULT_OPTIONS: Required<LightOptions> = {
        intensity: 1.0,
        color: new THREE.Color('#ffffff'),
        distance: 0,
        angle: Math.PI / 3,
        decay: 1,
        castShadow: false,
        position: [0, 0, 0]
    }

    constructor(type: LightType, options: LightOptions = {}) {
        // super(this.color, intensity);

        const mergedOptions = { ...Light.DEFAULT_OPTIONS, ...options }

        this.type = type;
        this.intensity = mergedOptions.intensity;
        this.color = new THREE.Color(mergedOptions.color)

        this.instance = this.createLight(mergedOptions);

        if ('position' in this.instance) {
            this.instance.position.set(...mergedOptions.position);
        }
    }

    private createLight(options: Required<LightOptions>): THREE.Light {
        switch (this.type) {
            case 'ambient':
                return new THREE.AmbientLight(this.color, this.intensity);

            case 'directional': {
                const light = new THREE.DirectionalLight(this.color, this.intensity);
                light.castShadow = options.castShadow;
                return light;
            }

            case 'point':
                return new THREE.PointLight(
                    this.color,
                    this.intensity,
                    options.distance,
                    options.decay
                );

            case 'spot': {
                const light = new THREE.SpotLight(
                    this.color,
                    this.intensity,
                    options.distance,
                    options.angle,
                    0.2, // penumbra
                    options.decay
                );
                light.castShadow = options.castShadow;
                return light;
            }

            default:
                throw new Error(`Unsupported light type: ${this.type satisfies never}`);
        }
    }

    public setPosition(x: number, y: number, z: number): void {
        if ('position' in this.instance) {
            this.instance.position.set(x, y, z);
        }
    }

    public dispose(): void {
        this.instance.dispose();
    }

    // 提供一个方法获取底层的 THREE.Light 实例
    public getObject3D(): THREE.Light {
        return this.instance;
    }
}